﻿using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Text;

namespace QExplorer
{
	[StructLayout(LayoutKind.Sequential)]
	public struct SHFILEINFO
	{
		public IntPtr hIcon;
		public int iIcon;
		public uint dwAttributes;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
		public string szDisplayName;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
		public string szTypeName;
	};

	class API
	{
		public const uint SHGFI_ICON = 0x100;
		public const uint SHGFI_LARGEICON = 0x0;
		public const uint SHGFI_SMALLICON = 0x1;
		public const uint SHGFI_LINKOVERLAY = 0x8000;
		public const uint SHGFI_SYSICONINDEX = 0x4000;
		public const uint SHGFI_OPENICON = 0x2;
		public const uint SHGFI_PIDL = 0x8;
		public const uint SHGFI_DISPLAYNAME = 0x200;
		public const uint SHGFI_TYPENAME = 0x400;
		public const uint SHGFI_SELECTED = 0x10000;
		public const uint SHGFI_ADDOVERLAYS = 0x20;


		public static IntPtr GetFileInfo(string filename, ref SHFILEINFO sfi,
			uint flag)
		{
			return SHGetFileInfo(filename, 0, ref sfi,
				Marshal.SizeOf(sfi), flag);
		}

		[DllImport("shell32.dll")]
		public static extern IntPtr SHGetFileInfo(
			string pszPath,
			uint dwFileAttributes,
			ref SHFILEINFO sfi,
			int cbSizeFileInfo,
			uint uFlags);
		[DllImport("shell32.dll")]
		public static extern IntPtr SHGetFileInfo(
			IntPtr pszPath,
			uint dwFileAttributes,
			ref SHFILEINFO sfi,
			int cbSizeFileInfo,
			uint uFlags);

		public static Icon GetIcon(int specialFolder)
		{
			IntPtr pidl = GetPIDL(specialFolder);
			SHFILEINFO sfi = new SHFILEINFO();
			SHGetFileInfo(pidl, 0, ref sfi, Marshal.SizeOf(sfi), 
				SHGFI_PIDL | SHGFI_ICON | SHGFI_LARGEICON);
			Icon icon = Icon.FromHandle(sfi.hIcon);
			return icon;
		}

		[DllImport("user32.dll")]
		public static extern bool DestroyIcon(IntPtr hIcon);

		public const int LVSIL_NORMAL = 0;
		public const int LVSIL_SMALL = 1;
		public const int LVSIL_STATE = 2;
		public const int LVSIL_GROUPHEADER = 3;

		public const uint LVM_SETIMAGELIST = 0x1003;
		public const uint TCM_SETIMAGELIST = 0x1303;

		public const int TVSIL_NORMAL = 0;
		public const int TTVSIL_STATE = 2;
		public const int TVM_SETIMAGELIST = 0x1109;

		[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
		public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
		[DllImport("kernel32.dll")]
		public static extern IntPtr GetLastError();

		public const int S_OK = 0;
		[DllImport("shell32.dll")]
		public static extern int SHGetDesktopFolder(out IntPtr ppshf);

		public static IShellFolder GetDesktopIShell()
		{
			IntPtr pIShell;
			SHGetDesktopFolder(out pIShell);
			return (IShellFolder)Marshal.GetObjectForIUnknown(pIShell);
		}
		public const int CSIDL_DESKTOP = 0x0000;
		public const int CSIDL_DESKTOPDIRECTORY = 0x0010;
		public const int CSIDL_PERSONAL = 0x0005;
		// 		public const int CSIDL_DESKTOPDIRECTORY = 0x0010;
		[DllImport("shell32.dll")]
		public static extern int SHGetSpecialFolderLocation(int owner, int folder, out IntPtr ppidl);

		public static IntPtr GetPIDL(int folder)
		{
			IntPtr pidl;
			SHGetSpecialFolderLocation(0, folder, out pidl);
			return pidl;
		}
	}

	[ComImport]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	[Guid("000214E6-0000-0000-C000-000000000046")]
	public interface IShellFolder
	{
		void ParseDisplayName(
			IntPtr hwnd,
			IntPtr pbc,
			[MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
			out uint pchEaten,
			out IntPtr ppidl,
			ref uint pdwAttributes);

		[PreserveSig]
		int EnumObjects(IntPtr hWnd, int flags, out IntPtr enumIDList);

		void BindToObject(
			IntPtr pidl,
			IntPtr pbc,
			[In()] ref Guid riid,
			out IShellFolder ppv);

		void BindToStorage(
			IntPtr pidl,
			IntPtr pbc,
			[In()] ref Guid riid,
			[MarshalAs(UnmanagedType.Interface)] out object ppv);

		[PreserveSig()]
		uint CompareIDs(
			int lParam,
			IntPtr pidl1,
			IntPtr pidl2);

		void CreateViewObject(
			IntPtr hwndOwner,
			[In()] ref Guid riid,
			[MarshalAs(UnmanagedType.Interface)] out object ppv);

		void GetAttributesOf(
			uint cidl,
			[In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
		   ref int rgfInOut);

		IntPtr GetUIObjectOf(
			IntPtr hwndOwner,
			uint cidl,
			[MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
			[In()] ref Guid riid,
			out IntPtr rgfReserved);

		void GetDisplayNameOf(
			IntPtr pidl,
			int uFlags,
			IntPtr lpName);

		IntPtr SetNameOf(
			IntPtr hwnd,
			IntPtr pidl,
			[MarshalAs(UnmanagedType.LPWStr)] string pszName,
		   int uFlags);
	}
}
